package leeFunciones;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JList;

import FanInFanOut.FanIn;
import FanInFanOut.FanOut;
import Halstead.Halstead;
import McCabe.NroCiclomatico;

public class LeeFunciones {

	static String regsdex = "(public|protected|private|static|\\s) +[\\w\\<\\>\\[\\]]+\\s+(\\w+) *\\([^\\)]*\\) *(\\{?|[^;])";
	static String regsdex2 = "[\\w\\<\\>\\[\\]]+\\s+(\\w+) *\\([^\\)]*\\) *(\\{?|[^;])";
	static Pattern pattern = Pattern.compile(regsdex);
	static Pattern pattern2 = Pattern.compile(regsdex2);

	private static Halstead halstead;
	private static NroCiclomatico nroCiclomatico;

	public static ArrayList<String> getFunciones(File file) throws IOException {
		FileReader fr = null;
		BufferedReader br = null;

		ArrayList<String> funciones = new ArrayList<String>();

		try {
			fr = new FileReader(file);
			br = new BufferedReader(fr);

			String linea = br.readLine();

			while (linea != null) {
				Matcher m = pattern.matcher(linea.trim());
				if (m.matches()) {
					funciones.add(m.group(2));
				} else {
					Matcher m2 = pattern2.matcher(linea.trim());
					if (m2.matches()) {
						funciones.add(m2.group(1));
					}
				}

				linea = br.readLine();
			}

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		br.close();

		Collections.sort(funciones, String.CASE_INSENSITIVE_ORDER);

		return funciones;
	}

	public static String getCuerpoFuncion(File file, String selectedValue) {
		// TODO Auto-generated method stub
		String funcion = new String();
		FileReader fr = null;
		BufferedReader br = null;
		try {
			fr = new FileReader(file);
			br = new BufferedReader(fr);
			boolean funcionLeida = false;
			String linea = br.readLine();

			boolean llavesCerradas = false;
			int contLlaves = 0;

			while (linea != null && !funcionLeida) {
				Matcher m = pattern.matcher(linea.trim());
				Matcher m2 = pattern2.matcher(linea.trim());
				if ((m.matches() || m2.matches())
						&& linea.contains(selectedValue)) {

					while (!linea.contains("{")) {
						funcion += linea + '\n';
						linea = br.readLine();
					}

					while (!llavesCerradas) {
						if (linea.contains("{"))
							contLlaves++;
						if (linea.contains("}"))
							contLlaves--;

						llavesCerradas = contLlaves == 0;
						funcion += linea + '\n';
						linea = br.readLine();

					}
					funcionLeida = true;
				}
				linea = br.readLine();
			}

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return funcion;

	}

	public static void aplicarHalstead(String textoFuncion) {

		halstead = new Halstead();
		halstead.aplicarMetodo(textoFuncion);
	}

	public static Integer getLongitud() {

		return halstead.longitud();
	}

	public static Double getVolumen() {

		return halstead.volumen();
	}

	public static int getLineasDeCodigo(String textoFuncion) {

		BufferedReader reader = new BufferedReader(new StringReader(
				textoFuncion));
		int lineasCodigoCount = 0;
		String linea;
		try {
			linea = reader.readLine();
			while (linea != null) {
				linea = linea.trim();
				if (!(linea.startsWith("//") || linea.equals("{")
						|| linea.equals("}") || linea.length() == 0))
					lineasCodigoCount++;

				linea = reader.readLine();
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return lineasCodigoCount;

	}

	public static int getLineasDeComentario(String textoFuncion) {

		BufferedReader reader = new BufferedReader(new StringReader(
				textoFuncion));
		int lineasComentarioCount = 0;
		String linea;
		try {
			linea = reader.readLine();
			while (linea != null) {
				linea = linea.trim();
				if (linea.startsWith("//") || linea.startsWith("/*"))
					lineasComentarioCount++;

				linea = reader.readLine();
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return lineasComentarioCount;

	}

	public static void aplicarNroCiclomatico(String textoFuncion) {

		nroCiclomatico = new NroCiclomatico();
		nroCiclomatico.ProcesarMetodo(textoFuncion);

	}
	
	public static Integer getNroCiclomatico(){
		
		return nroCiclomatico.informarNroCiclomatico();
	}
	
	public static String getNodosCondicion() {
		
		return nroCiclomatico.informarNodosCondicion();
	}

	public static Integer getFanIn(String textoFuncion, JList metodosNombre) {

		return FanIn.aplicarMetodo(textoFuncion, metodosNombre);

	}

	public static Integer getFanOut(File file, String metodosNombre) {

		return FanOut.aplicarMetodo(file, metodosNombre);

	}
}
